<?php
namespace lib;

use think\facade\Cache;

/**
 * 阿里大于短信
 * Class SmsAli
 * @package app\common\lib
 */
class SmsAli
{
    // 保存错误信息
    public $error;

    // Access Key ID
    private $accessKeyId = '';

    // Access Access Key Secret
    private $accessKeySecret = '';

    // 签名
    private $signName = '';

    public function __construct($config = []) {

        if( empty($config) ) {
            $config = array (
                'accessKeyId' => xn_cfg('sms.ali_accessKeyId'),
                'accessKeySecret' => xn_cfg('sms.ali_accessKeySecret'),
                'signName' => xn_cfg('sms.ali_signName'),
            );
        }

        // 配置参数
        $this->accessKeyId = $config ['accessKeyId'];
        $this->accessKeySecret = $config ['accessKeySecret'];
        $this->signName = $config ['signName'];
    }

    /**
     * 发送短信验证码
     * @param string $mobile
     * @param string $TemplateParam
     * @param string $templateCode
     * @param string $msg
     * @return bool
     */
    public function send($mobile, $TemplateParam = [], $templateCode='', &$msg='' ) {

        if( $mobile=='' ) {
            $msg = '请输入手机号码';
            return false;
        }
        if( !$this->isMobile($mobile) ) {
            $msg = '请输入正确的手机号码';
            return false;
        }
        if( $this->getIntervalTime($mobile) ) {
            $msg = '短信发送过于频繁';
            return false;
        }

        $params = array (
            'SignName' => $this->signName,
            'Format' => 'JSON',
            'Version' => '2017-05-25',
            'AccessKeyId' => $this->accessKeyId,
            'SignatureVersion' => '1.0',
            'SignatureMethod' => 'HMAC-SHA1',
            'SignatureNonce' => uniqid (),
            'Timestamp' => gmdate ( 'Y-m-d\TH:i:s\Z' ),
            'Action' => 'SendSms',
            'TemplateCode' => $templateCode,
            'PhoneNumbers' => $mobile,
            'TemplateParam' => !empty($TemplateParam) ? json_encode($TemplateParam) : '',
            //'TemplateParam' => '{"code":"' . $code . '"}'
        );
        $params ['Signature'] = $this->computeSignature ( $params, $this->accessKeySecret );
        $url = 'http://dysmsapi.aliyuncs.com/?' . http_build_query ( $params );
        $ch = curl_init ();
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt ( $ch, CURLOPT_TIMEOUT, 10 );
        $result = curl_exec ( $ch );
        curl_close ( $ch );
        $result = json_decode ( $result, true );
        if (isset ( $result ['Code'] ) && $result ['Code']== 'OK') {
            return true;
        } else {
            //错误信息 https://api.alidayu.com/doc2/apiDetail?spm=a3142.7629140.1.19.SmdYoA&apiId=25450
            $msg = "错误代码{$result ['Code']}：{$result ['Message']}";
            return false;
        }

    }

    private function percentEncode($string) {
        $string = urlencode ( $string );
        $string = preg_replace ( '/\+/', '%20', $string );
        $string = preg_replace ( '/\*/', '%2A', $string );
        $string = preg_replace ( '/%7E/', '~', $string );
        return $string;
    }

    /**
     * 签名
     * @param $parameters
     * @param $accessKeySecret
     * @return string
     */
    private function computeSignature($parameters, $accessKeySecret) {
        ksort ( $parameters );
        $canonicalizedQueryString = '';
        foreach ( $parameters as $key => $value ) {
            $canonicalizedQueryString .= '&' . $this->percentEncode ( $key ) . '=' . $this->percentEncode ( $value );
        }
        $stringToSign = 'GET&%2F&' . $this->percentencode ( substr ( $canonicalizedQueryString, 1 ) );
        $signature = base64_encode ( hash_hmac ( 'sha1', $stringToSign, $accessKeySecret . '&', true ) );
        return $signature;

    }

    /**
     * 验证短信验证码是否正确
     * @param $phone
     * @param $code
     * @return bool
     */
    public function checkCode($mobile, $code)
    {
        $o_code = $this->getCode($mobile);
        if( $o_code != $mobile . $code ) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 记住手机验证码
     * @param $mobile
     * @param $code
     */
    public function setCode($mobile, $code, $sec=300)
    {
        $key = md5('code_'.$mobile);
        Cache::set($key, $mobile . $code, intval($sec));
    }

    /**
     * 获取已经设置的手机验证码
     * @param $type
     * @return mixed
     */
    public function getCode($mobile)
    {
        $key = md5('code_'.$mobile);
        return Cache::get($key);
    }

    //是否是手机
    public function isMobile($mobile)
    {
        return preg_match("/^1[0-9]{10}$/",$mobile);
    }

    //设置短信发送的间隔时间
    public function setIntervalTime($mobile, $interval_time=60)
    {
        $key = md5($mobile.'_interval_time');
        Cache::set($key, 1, intval($interval_time));
    }

    //缓存的间隔时间是否还存在
    public function getIntervalTime($mobile)
    {
        $key = md5($mobile.'_interval_time');
        return Cache::get($key);
    }
}